import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../core/constants.dart';

/// 图像处理服务
class ImageProcessorService {
  // 单例模式实现
  static final ImageProcessorService _instance = ImageProcessorService._internal();
  factory ImageProcessorService() => _instance;
  ImageProcessorService._internal();
  
  // =================== 缓存系统 ===================
  final Map<String, ui.Image> _processedImageCache = {};
  final Map<String, Uint8List> _rawBytesCache = {};
  final Map<String, ImageInfo> _imageInfoCache = {};
  final Set<String> _processingImages = {};
  
  // =================== 性能统计 ===================
  int _cacheHits = 0;
  int _cacheMisses = 0;
  int _totalProcessed = 0;
  final Map<String, Duration> _processingTimes = {};
  
  /// 预处理图片用于拼图游戏
  Future<ui.Image> preprocessImageForPuzzle(String imagePath) async {
    final stopwatch = Stopwatch()..start();
    
    try {
      // 检查缓存
      if (_processedImageCache.containsKey(imagePath)) {
        _cacheHits++;
        debugPrint('💾 [ImageProcessor] 缓存命中: $imagePath');
        return _processedImageCache[imagePath]!;
      }
      
      _cacheMisses++;
      
      // 检查是否正在处理
      if (_processingImages.contains(imagePath)) {
        debugPrint('⏳ [ImageProcessor] 等待处理完成: $imagePath');
        await _waitForProcessingCompletion(imagePath);
        return _processedImageCache[imagePath]!;
      }
      
      _processingImages.add(imagePath);
      debugPrint('🖼️ [ImageProcessor] 开始预处理图片: $imagePath');
      
      // 第一步：加载原始图片数据
      final rawBytes = await _loadRawImageBytes(imagePath);
      
      // 第二步：解码并优化图片
      final processedImage = await _decodeAndOptimizeImage(
        rawBytes,
        targetSize: AppConstants.puzzleBoardSize.toInt(),
        quality: ImageQuality.high,
      );
      
      // 第三步：缓存结果
      _processedImageCache[imagePath] = processedImage;
      _rawBytesCache[imagePath] = rawBytes;
      
      // 第四步：缓存图片信息
      _imageInfoCache[imagePath] = ImageInfo(
        path: imagePath,
        width: processedImage.width,
        height: processedImage.height,
        sizeInBytes: rawBytes.length,
        format: _detectImageFormat(rawBytes),
        processingTime: stopwatch.elapsed,
      );
      
      _totalProcessed++;
      debugPrint('✅ [ImageProcessor] 预处理完成: ${processedImage.width}x${processedImage.height} 用时: ${stopwatch.elapsedMilliseconds}ms');
      
      return processedImage;
      
    } catch (e) {
      debugPrint('❌ [ImageProcessor] 图片预处理失败 $imagePath: $e');
      rethrow;
    } finally {
      _processingImages.remove(imagePath);
      _processingTimes[imagePath] = stopwatch.elapsed;
      stopwatch.stop();
    }
  }
  
  /// 加载原始图片字节数据
  Future<Uint8List> _loadRawImageBytes(String imagePath) async {
    try {
      final ByteData data = await rootBundle.load(imagePath);
      return data.buffer.asUint8List();
    } catch (e) {
      throw ImageProcessingException('无法加载图片资源: $imagePath', e);
    }
  }
  
  /// 解码并优化图片
  Future<ui.Image> _decodeAndOptimizeImage(
    Uint8List bytes, {
    required int targetSize,
    required ImageQuality quality,
  }) async {
    try {
      final ui.Codec codec = await ui.instantiateImageCodec(
        bytes,
        targetWidth: targetSize,
        targetHeight: targetSize,
        allowUpscaling: false,
      );
      
      final ui.FrameInfo frame = await codec.getNextFrame();
      codec.dispose();
      
      return frame.image;
      
    } catch (e) {
      throw ImageProcessingException('图像解码失败', e);
    }
  }
  
  /// 等待处理完成
  Future<void> _waitForProcessingCompletion(String imagePath) async {
    const maxWaitTime = Duration(seconds: 30);
    final startTime = DateTime.now();
    
    while (_processingImages.contains(imagePath)) {
      await Future.delayed(const Duration(milliseconds: 50));
      
      if (DateTime.now().difference(startTime) > maxWaitTime) {
        throw ImageProcessingException('图片处理超时: $imagePath', null);
      }
    }
  }
  
  /// 检测图片格式
  ImageFormat _detectImageFormat(Uint8List bytes) {
    if (bytes.length < 4) return ImageFormat.unknown;
    
    // JPEG格式检测
    if (bytes[0] == 0xFF && bytes[1] == 0xD8) {
      return ImageFormat.jpeg;
    }
    
    // PNG格式检测
    if (bytes[0] == 0x89 && 
        bytes[1] == 0x50 && 
        bytes[2] == 0x4E && 
        bytes[3] == 0x47) {
      return ImageFormat.png;
    }
    
    // WebP格式检测
    if (bytes.length >= 12 &&
        bytes[0] == 0x52 && bytes[1] == 0x49 && 
        bytes[2] == 0x46 && bytes[3] == 0x46 &&
        bytes[8] == 0x57 && bytes[9] == 0x45 && 
        bytes[10] == 0x42 && bytes[11] == 0x50) {
      return ImageFormat.webp;
    }
    
    return ImageFormat.unknown;
  }
  
  /// 预加载图片（异步，不阻塞UI）
  void preloadImage(String imagePath) {
    if (_processedImageCache.containsKey(imagePath)) {
      return;
    }
    
    // 修复缺少返回值的问题
    preprocessImageForPuzzle(imagePath).catchError((e) {
      debugPrint('⚠️ [ImageProcessor] 预加载失败 $imagePath: $e');
      return _createFallbackImage(); // 返回fallback图像
    });
  }
  
  /// 创建fallback图像
  Future<ui.Image> _createFallbackImage() async {
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder);
    final paint = Paint()..color = Colors.grey;
    
    canvas.drawRect(const Rect.fromLTWH(0, 0, 100, 100), paint);
    
    final picture = recorder.endRecording();
    final image = await picture.toImage(100, 100);
    picture.dispose();
    
    return image;
  }
  
  /// 获取图片信息
  Future<ImageInfo> getImageInfo(String imagePath) async {
    if (_imageInfoCache.containsKey(imagePath)) {
      return _imageInfoCache[imagePath]!;
    }
    
    await preprocessImageForPuzzle(imagePath);
    return _imageInfoCache[imagePath]!;
  }
  
  /// 清理缓存
  void clearCache() {
    debugPrint('🧹 [ImageProcessor] 清理图片缓存');
    
    for (final image in _processedImageCache.values) {
      image.dispose();
    }
    
    _processedImageCache.clear();
    _rawBytesCache.clear();
    _imageInfoCache.clear();
    _processingImages.clear();
    
    _cacheHits = 0;
    _cacheMisses = 0;
    _processingTimes.clear();
    
    debugPrint('✅ [ImageProcessor] 缓存清理完成');
  }
  
  /// 获取性能统计
  ImageProcessorStats getPerformanceStats() {
    return ImageProcessorStats(
      totalProcessed: _totalProcessed,
      cacheHits: _cacheHits,
      cacheMisses: _cacheMisses,
      cacheHitRate: _cacheHits + _cacheMisses > 0 
          ? _cacheHits / (_cacheHits + _cacheMisses) 
          : 0.0,
      averageProcessingTime: _processingTimes.isEmpty 
          ? Duration.zero 
          : Duration(
              milliseconds: _processingTimes.values
                  .map((d) => d.inMilliseconds)
                  .reduce((a, b) => a + b) ~/ _processingTimes.length
            ),
      currentCacheSize: _processedImageCache.length,
      totalMemoryUsage: _estimateMemoryUsage(),
    );
  }
  
  /// 估算内存使用量
  int _estimateMemoryUsage() {
    int totalBytes = 0;
    
    for (final image in _processedImageCache.values) {
      totalBytes += image.width * image.height * 4;
    }
    
    for (final bytes in _rawBytesCache.values) {
      totalBytes += bytes.length;
    }
    
    return totalBytes;
  }
}

// =================== 数据模型 ===================

class ImageInfo {
  final String path;
  final int width;
  final int height;
  final int sizeInBytes;
  final ImageFormat format;
  final Duration processingTime;
  
  const ImageInfo({
    required this.path,
    required this.width,
    required this.height,
    required this.sizeInBytes,
    required this.format,
    required this.processingTime,
  });
  
  String get formattedSize {
    if (sizeInBytes < 1024) return '${sizeInBytes}B';
    if (sizeInBytes < 1024 * 1024) return '${(sizeInBytes / 1024).toStringAsFixed(1)}KB';
    return '${(sizeInBytes / (1024 * 1024)).toStringAsFixed(1)}MB';
  }
  
  @override
  String toString() => 'ImageInfo(${width}x$height, $formattedSize, $format)';
}

enum ImageFormat {
  jpeg('JPEG'),
  png('PNG'),
  webp('WebP'),
  unknown('Unknown');
  
  const ImageFormat(this.displayName);
  final String displayName;
}

enum ImageQuality {
  low(60),
  medium(80),
  high(90),
  maximum(100);
  
  const ImageQuality(this.value);
  final int value;
}

class ImageProcessorStats {
  final int totalProcessed;
  final int cacheHits;
  final int cacheMisses;
  final double cacheHitRate;
  final Duration averageProcessingTime;
  final int currentCacheSize;
  final int totalMemoryUsage;
  
  const ImageProcessorStats({
    required this.totalProcessed,
    required this.cacheHits,
    required this.cacheMisses,
    required this.cacheHitRate,
    required this.averageProcessingTime,
    required this.currentCacheSize,
    required this.totalMemoryUsage,
  });
}

class ImageProcessingException implements Exception {
  final String message;
  final dynamic originalError;
  
  const ImageProcessingException(this.message, this.originalError);
  
  @override
  String toString() => 'ImageProcessingException: $message${originalError != null ? ' ($originalError)' : ''}';
}
